<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>My Blog</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="This is my first blog.">
<meta property="og:type" content="website">
<meta property="og:title" content="My Blog">
<meta property="og:url" content="http://yoursite.com/page/4/index.html">
<meta property="og:site_name" content="My Blog">
<meta property="og:description" content="This is my first blog.">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="Alanisia">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/atom.xml" title="My Blog" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.ico">
  
  
    <link href="//fonts.googleapis.com/css?family=Source+Code+Pro" rel="stylesheet" type="text/css">
  
  
<link rel="stylesheet" href="/css/style.css">

<meta name="generator" content="Hexo 4.2.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">My Blog</a>
      </h1>
      
        <h2 id="subtitle-wrap">
          <a href="/" id="subtitle">我的博客 -- 记录编程过程中所遇到的问题与总结</a>
        </h2>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="搜索"></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="http://yoursite.com"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main">
  
    <article id="post-sublimetext" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/sublimetext/" class="article-date">
  <time datetime="2020-10-31T00:21:48.000Z" itemprop="datePublished">2020-10-31</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/sublimetext/">Sublime text安装</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p> 安装GPG key:        </p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget -qO - https://download.sublimetext.com/sublimehq-pub.gpg | sudo apt-key add -</span><br></pre></td></tr></table></figure>

<p>确保将apt设置为可与https来源一起使用：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install apt-transport-https</span><br></pre></td></tr></table></figure>

<p>选择要使用的频道：   </p>
<ul>
<li><p>Stable</p>
<p><code>echo &quot;deb https://download.sublimetext.com/ apt/stable/&quot; | sudo tee /etc/apt/sources.list.d/sublime-text.list</code></p>
</li>
<li><p>Dev</p>
<p><code>echo &quot;deb https://download.sublimetext.com/ apt/dev/&quot; | sudo tee /etc/apt/sources.list.d/sublime-text.list</code></p>
</li>
</ul>
<p>更新apt源并安装Sublime Text：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install sublime-text</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/sublimetext/" data-id="ckpb8zvkj0024dsvl1svu5z54" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/sublime-text/" rel="tag">sublime text</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-apt-mirrors" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/apt-mirrors/" class="article-date">
  <time datetime="2020-10-31T00:06:15.000Z" itemprop="datePublished">2020-10-31</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/apt-mirrors/">apt镜像源</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>Ubuntu 20.04版代号为focal，18.04版代号为bionic。</p>
<h2 id="阿里"><a href="#阿里" class="headerlink" title="阿里"></a>阿里</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ focal main restricted universe multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ focal-proposed main restricted universe multiverse</span><br><span class="line">deb http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors.aliyun.com/ubuntu/ focal-backports main restricted universe multiverse</span><br></pre></td></tr></table></figure>

<h2 id="清华"><a href="#清华" class="headerlink" title="清华"></a>清华</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse</span><br><span class="line"><span class="comment"># deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal main restricted universe multiverse</span></span><br><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line"><span class="comment"># deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-updates main restricted universe multiverse</span></span><br><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse</span><br><span class="line"><span class="comment"># deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-backports main restricted universe multiverse</span></span><br><span class="line">deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line"><span class="comment"># deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-security main restricted universe multiverse</span></span><br><span class="line"></span><br><span class="line"><span class="comment"># deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse</span></span><br><span class="line"><span class="comment"># deb-src https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse</span></span><br></pre></td></tr></table></figure>

<h2 id="网易"><a href="#网易" class="headerlink" title="网易"></a>网易</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">deb http://mirrors<span class="number">.163</span>.com/ubuntu/ focal main restricted universe multiverse</span><br><span class="line">deb http://mirrors<span class="number">.163</span>.com/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line">deb http://mirrors<span class="number">.163</span>.com/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line">deb http://mirrors<span class="number">.163</span>.com/ubuntu/ focal-proposed main restricted universe multiverse</span><br><span class="line">deb http://mirrors<span class="number">.163</span>.com/ubuntu/ focal-backports main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors<span class="number">.163</span>.com/ubuntu/ focal main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors<span class="number">.163</span>.com/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors<span class="number">.163</span>.com/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors<span class="number">.163</span>.com/ubuntu/ focal-proposed main restricted universe multiverse</span><br><span class="line">deb-src http://mirrors<span class="number">.163</span>.com/ubuntu/ focal-backports main restricted universe multiverse</span><br></pre></td></tr></table></figure>

<h2 id="中科大"><a href="#中科大" class="headerlink" title="中科大"></a>中科大</h2><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">deb https://mirrors.ustc.edu.cn/ubuntu/ focal main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.ustc.edu.cn/ubuntu/ focal main restricted universe multiverse</span><br><span class="line">deb https://mirrors.ustc.edu.cn/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.ustc.edu.cn/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line">deb https://mirrors.ustc.edu.cn/ubuntu/ focal-backports main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.ustc.edu.cn/ubuntu/ focal-backports main restricted universe multiverse</span><br><span class="line">deb https://mirrors.ustc.edu.cn/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.ustc.edu.cn/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line">deb https://mirrors.ustc.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.ustc.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse</span><br></pre></td></tr></table></figure>

<h2 id="广工"><a href="#广工" class="headerlink" title="广工"></a>广工</h2><p>广工校园网可用</p>
<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">deb https://mirrors.gdut.edu.cn/ubuntu/ focal main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.gdut.edu.cn/ubuntu/ focal main restricted universe multiverse</span><br><span class="line">deb https://mirrors.gdut.edu.cn/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.gdut.edu.cn/ubuntu/ focal-updates main restricted universe multiverse</span><br><span class="line">deb https://mirrors.gdut.edu.cn/ubuntu/ focal-backports main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.gdut.edu.cn/ubuntu/ focal-backports main restricted universe multiverse</span><br><span class="line">deb https://mirrors.gdut.edu.cn/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.gdut.edu.cn/ubuntu/ focal-security main restricted universe multiverse</span><br><span class="line">deb https://mirrors.gdut.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse</span><br><span class="line">deb-src https://mirrors.gdut.edu.cn/ubuntu/ focal-proposed main restricted universe multiverse</span><br></pre></td></tr></table></figure>


      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/apt-mirrors/" data-id="ckpb8zvjl000hdsvlfosrfkqu" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/linux/" rel="tag">linux</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-ubuntu-pppoe" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/ubuntu-pppoe/" class="article-date">
  <time datetime="2020-10-31T00:05:51.000Z" itemprop="datePublished">2020-10-31</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/ubuntu-pppoe/">ubuntu之pppoe拨号连接</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h2 id="pppoeconf"><a href="#pppoeconf" class="headerlink" title="pppoeconf"></a>pppoeconf</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo pppoeconf</span><br></pre></td></tr></table></figure>

<p>一步一步跟着操作设置。一路yes即可；设置后，</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># 联网</span></span><br><span class="line">sudo pon dsl-provider</span><br><span class="line"><span class="comment"># 断网</span></span><br><span class="line">sudo poff</span><br></pre></td></tr></table></figure>

<h2 id="nmcli"><a href="#nmcli" class="headerlink" title="nmcli"></a>nmcli</h2><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmcli con edit <span class="built_in">type</span> pppoe con-name <span class="string">"connection 1"</span> <span class="comment"># 设置连接名</span></span><br></pre></td></tr></table></figure>

<p>执行该命令后，在命令行交互界面输入：</p>
<figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">set pppoe.username YOUR_DSL_ACCOUNT_USERNAME</span><br><span class="line">set pppoe.password YOUR_DSL_ACCOUNT_PASSWORD</span><br><span class="line">save</span><br></pre></td></tr></table></figure>

<p>接下来会询问是否想设置自动连接，输入yes即可开启开机自动连接。</p>
<p>输入quit退出。</p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/ubuntu-pppoe/" data-id="ckpb8zvl00030dsvld8ejb4ce" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/linux/" rel="tag">linux</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-vala" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/vala/" class="article-date">
  <time datetime="2020-10-17T14:50:29.000Z" itemprop="datePublished">2020-10-17</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/vala/">Vala</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>Vala 是一门新兴的编程语言，由 Gnome 主导开发，支持很多现代语言特性，借鉴了大量的 C# 语法，Python 的手感，C 的执行速度，Vala 最终会转换为 C 语言，然后把 C 代码编译为二进制文件，使用 Vala 编写应用程序和直接使用 C 语言编写应用程序，运行效率是一样的，但是 Vala 相比 C 语言更加容易，可以快速编写和维护。</p>
<h2 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h2><h3 id="安装valac编译器"><a href="#安装valac编译器" class="headerlink" title="安装valac编译器"></a>安装valac编译器</h3><p>安装0.48版vala：</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># Ubuntu 18.04 </span></span><br><span class="line">sudo add-apt-repository ppa:vala-team</span><br><span class="line"><span class="comment"># On some older versions of Ubuntu you may need to install the add-apt-repository tool first:</span></span><br><span class="line">sudo apt-get install software-properties-common</span><br><span class="line"><span class="comment"># Then you can install the latest version:</span></span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install valac</span><br></pre></td></tr></table></figure>

<h3 id="安装LSP"><a href="#安装LSP" class="headerlink" title="安装LSP"></a>安装LSP</h3><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo add-apt-repository ppa:prince781/vala-language-server</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install vala-language-server</span><br></pre></td></tr></table></figure>

<h3 id="源码安装"><a href="#源码安装" class="headerlink" title="源码安装"></a>源码安装</h3><p>所需要的依赖有：flex, bison, glib(&gt;= 2.40), libgvc(&gt;= 2.16)；</p>
<figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># clone from gitlab</span></span><br><span class="line">git <span class="built_in">clone</span> git@gitlab.gnome.org:GNOME/vala.git</span><br><span class="line"><span class="comment"># or</span></span><br><span class="line">git <span class="built_in">clone</span> https://gitlab.gnome.org/GNOME/vala.git</span><br></pre></td></tr></table></figure>

<p>或者从这里下载：<a href="https://mirrors.nju.edu.cn/gnome/sources/vala/0.50/vala-0.50.1.tar.xz。" target="_blank" rel="noopener">https://mirrors.nju.edu.cn/gnome/sources/vala/0.50/vala-0.50.1.tar.xz。</a></p>
<h4 id="构建"><a href="#构建" class="headerlink" title="构建"></a>构建</h4><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">tar -Jxvf vala-xx.tar.xz</span><br><span class="line"><span class="built_in">cd</span> vala-xx</span><br><span class="line">./configure</span><br><span class="line">make</span><br></pre></td></tr></table></figure>

<h3 id="安装Vim相关支持"><a href="#安装Vim相关支持" class="headerlink" title="安装Vim相关支持"></a>安装Vim相关支持</h3><p>确保已安装Vim-plug，在<code>.vimrc</code>文件中写入：</p>
<figure class="highlight vbscript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">call</span> plug#begin(<span class="comment">'~/.vim/plugged')</span></span><br><span class="line">	Plug <span class="comment">'arrufat/vala.vim'</span></span><br><span class="line">	Plug <span class="comment">'neoclide/coc.nvim',&#123;'branch': 'release'&#125;</span></span><br><span class="line"><span class="keyword">call</span> plug#<span class="keyword">end</span>()</span><br></pre></td></tr></table></figure>

<p>执行<code>:PlugInstall</code>，这会安装vala.vim和coc.nvim两个插件。</p>
<p>执行<code>:CocConfig</code>打开coc配置文件，配置vala的LSP，以启用代码补全和语法检查：</p>
<figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">    <span class="attr">"languageserver"</span>: &#123;</span><br><span class="line">        <span class="attr">"vala"</span>: &#123;</span><br><span class="line">            <span class="attr">"command"</span>: <span class="string">"vala-language-server"</span>,</span><br><span class="line">            <span class="attr">"filetypes"</span>: [<span class="string">"vala"</span>]</span><br><span class="line">        &#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>参考链接：<a href="https://www.jianshu.com/p/77592fffd939。" target="_blank" rel="noopener">https://www.jianshu.com/p/77592fffd939。</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/vala/" data-id="ckpb8zvkz002ydsvlesnseibj" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/vala/" rel="tag">vala</a></li></ul>

    </footer>
  </div>
  
</article>


  
    <article id="post-epoll" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/epoll/" class="article-date">
  <time datetime="2020-10-12T23:18:21.000Z" itemprop="datePublished">2020-10-12</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="article-title" href="/epoll/">Epoll - I/O event notification facility</a>
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <p>在linux的网络编程中，很长的时间都在使用select来做事件触发。在linux新的内核中，有了一种替换它的机制，就是epoll。</p>
<p>相比于select，epoll最大的好处在于它不会随着监听fd数目的增长而降低效率。因为在内核中的select实现中，它是采用轮询来处理的，轮询的fd数目越多，自然耗时越多。并且，在<code>linux/posix_types.h</code>头文件有这样的声明：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">define</span> __FD_SETSIZE  1024</span></span><br></pre></td></tr></table></figure>

<p>表示select最多同时监听1024个fd，当然，可以通过修改头文件再重编译内核来扩大这个数目，但这似乎并不治本。</p>
<p>epoll的接口非常简单，一共就三个函数：</p>
<ol>
<li><p><code>int epoll_create(int size);</code></p>
<p>创建一个epoll的句柄，size用来告诉内核这个监听的数目一共有多大。这个参数不同于select()中的第一个参数，给出最大监听的fd+1的值。需要注意的是，当创建好epoll句柄后，它就是会占用一个fd值，在linux下如果查看/proc/进程id/fd/，是能够看到这个fd的，所以在使用完epoll后，必须调用close()关闭，否则可能导致fd被耗尽。</p>
</li>
<li><p><code>int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);</code><br>epoll的事件注册函数，它不同与select()是在监听事件时告诉内核要监听什么类型的事件，而是在这里先注册要监听的事件类型。第一个参数是<code>epoll_create()</code>的返回值，第二个参数表示动作，用三个宏来表示：<br><code>EPOLL_CTL_ADD</code>：注册新的fd到epfd中；<br><code>EPOLL_CTL_MOD</code>：修改已经注册的fd的监听事件；<br><code>EPOLL_CTL_DEL</code>：从epfd中删除一个fd；<br>第三个参数是需要监听的fd，第四个参数是告诉内核需要监听什么事，<code>struct epoll_event</code>结构如下：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">typedef</span> <span class="keyword">union</span> epoll_data &#123;</span><br><span class="line">   <span class="keyword">void</span> *ptr;</span><br><span class="line">   <span class="keyword">int</span> fd;</span><br><span class="line">   <span class="keyword">__uint32_t</span> u32;</span><br><span class="line">   <span class="keyword">__uint64_t</span> u64;</span><br><span class="line">&#125; <span class="keyword">epoll_data_t</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">struct</span> <span class="title">epoll_event</span> &#123;</span></span><br><span class="line">   <span class="keyword">__uint32_t</span> events; <span class="comment">/* Epoll events */</span></span><br><span class="line">   <span class="keyword">epoll_data_t</span> data; <span class="comment">/* User data variable */</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure>

<p>events可以是以下几个宏的集合：</p>
<ul>
<li>EPOLLIN ：表示对应的文件描述符可以读（包括对端SOCKET正常关闭）；</li>
<li>EPOLLOUT：表示对应的文件描述符可以写；</li>
<li>EPOLLPRI：表示对应的文件描述符有紧急的数据可读（这里应该表示有带外数据到来）；</li>
<li>EPOLLERR：表示对应的文件描述符发生错误；</li>
<li>EPOLLHUP：表示对应的文件描述符被挂断；</li>
<li>EPOLLET： 将EPOLL设为边缘触发(Edge Triggered)模式，这是相对于水平触发(Level Triggered)来说的；</li>
<li>EPOLLONESHOT：只监听一次事件，当监听完这次事件之后，如果还需要继续监听这个socket的话，需要再次把这个socket加入到EPOLL队列里。</li>
</ul>
</li>
<li><p><code>int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);</code><br>等待事件的产生，类似于select()调用。参数events用来从内核得到事件的集合，maxevents告之内核这个events有多大，这个 maxevents的值不能大于创建epoll_create()时的size，参数timeout是超时时间（毫秒，0会立即返回，-1将不确定，也有说法说是永久阻塞）。该函数返回需要处理的事件数目，如返回0表示已超时。</p>
</li>
<li><p>关于ET、LT两种工作模式：<br>可以得出这样的结论:<br>ET模式仅当状态发生变化的时候才获得通知,这里所谓的状态的变化并不包括缓冲区中还有未处理的数据,也就是说,如果要采用ET模式,需要一直read/write直到出错为止,很多人反映为什么采用ET模式只接收了一部分数据就再也得不到通知了,大多因为这样;而LT模式是只要有数据没有处理就会一直通知下去的。</p>
</li>
</ol>
<p>那么究竟如何来使用epoll呢？其实非常简单。</p>
<p>通过在包含一个头文件<code>#include &lt;sys/epoll.h&gt;</code>以及几个简单的API将可以大大的提高你的网络服务器的支持人数。</p>
<p>首先通过<code>create_epoll(int maxfds)</code>来创建一个epoll的句柄，其中maxfds为你epoll所支持的最大句柄数。这个函数会返回一个新的epoll句柄，之后的所有操作将通过这个句柄来进行操作。在用完之后，记得用<code>close()</code>来关闭这个创建出来的epoll句柄。</p>
<p>之后在你的网络主循环里面，每一帧的调用<code>epoll_wait(int epfd, epoll_event events, int max events, int timeout)</code>来查询所有的网络接口，看哪一个可以读，哪一个可以写了。基本的语法为：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nfds = epoll_wait(kdpfd, events, maxevents, <span class="number">-1</span>);</span><br></pre></td></tr></table></figure>


<p>其中kdpfd为用<code>epoll_create</code>创建之后的句柄，events是一个<code>epoll_event*</code>的指针，当<code>epoll_wait</code>这个函数操作成功之后，<code>epoll_events</code>里面将储存所有的读写事件。<code>max_events</code>是当前需要监听的所有socket句柄数。最后一个timeout是<code>epoll_wait</code>的超时，为0的时候表示马上返回，为-1的时候表示一直等下去，直到有事件范围，为任意正整数的时候表示等这么长的时间，如果一直没有事件，则范围。一般如果网络主循环是单独的线程的话，可以用-1来等，这样可以保证一些效率，如果是和主逻辑在同一个线程的话，则可以用0来保证主循环的效率。</p>
<p><code>epoll_wait</code>范围之后应该是一个循环，遍利所有的事件。</p>
<p>几乎所有的epoll程序都使用下面的框架：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">for</span>( ; ; )</span><br><span class="line">   &#123;</span><br><span class="line">     nfds = epoll_wait(epfd,events,<span class="number">20</span>,<span class="number">500</span>);</span><br><span class="line">     <span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;nfds;++i)</span><br><span class="line">     &#123;</span><br><span class="line">       <span class="keyword">if</span>(events[i].data.fd==listenfd) <span class="comment">//有新的连接</span></span><br><span class="line">       &#123;</span><br><span class="line">         connfd = accept(listenfd,(sockaddr *)&amp;clientaddr, &amp;clilen); <span class="comment">//accept这个连接</span></span><br><span class="line">         ev.data.fd=connfd;</span><br><span class="line">         ev.events=EPOLLIN|EPOLLET;</span><br><span class="line">         epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&amp;ev); <span class="comment">//将新的fd添加到epoll的监听队列中</span></span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">else</span> <span class="keyword">if</span>( events[i].events&amp;EPOLLIN ) <span class="comment">//接收到数据，读socket</span></span><br><span class="line">       &#123;</span><br><span class="line">         n = <span class="built_in">read</span>(sockfd, <span class="built_in">line</span>, MAXLINE)) &lt; <span class="number">0</span>   <span class="comment">//读</span></span><br><span class="line">         ev.data.ptr = md;    <span class="comment">//md为自定义类型，添加数据</span></span><br><span class="line">         ev.events=EPOLLOUT|EPOLLET;</span><br><span class="line">         epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&amp;ev);<span class="comment">//修改标识符，等待下一个循环时发送数据，异步处理的精髓</span></span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">else</span> <span class="keyword">if</span>(events[i].events&amp;EPOLLOUT) <span class="comment">//有数据待发送，写socket</span></span><br><span class="line">       &#123;</span><br><span class="line">         struct myepoll_data* md = (myepoll_data*)events[i].data.ptr;   <span class="comment">//取数据</span></span><br><span class="line">         sockfd = md-&gt;fd;</span><br><span class="line">         send( sockfd, md-&gt;ptr, <span class="built_in">strlen</span>((<span class="keyword">char</span>*)md-&gt;ptr), <span class="number">0</span> );     <span class="comment">//发送数据</span></span><br><span class="line">         ev.data.fd=sockfd;</span><br><span class="line">         ev.events=EPOLLIN|EPOLLET;</span><br><span class="line">         epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&amp;ev); <span class="comment">//修改标识符，等待下一个循环时接收数据</span></span><br><span class="line">       &#125;</span><br><span class="line">       <span class="keyword">else</span></span><br><span class="line">       &#123;</span><br><span class="line">         <span class="comment">//其他的处理</span></span><br><span class="line">       &#125;</span><br><span class="line">     &#125;</span><br><span class="line">   &#125;</span><br></pre></td></tr></table></figure>

<p>下面给出一个完整的服务器端例子：</p>
<figure class="highlight c++"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/socket.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;sys/epoll.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;netinet/in.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;arpa/inet.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;fcntl.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;unistd.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;errno.h&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</span><br><span class="line"></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> MAXLINE 5</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> OPEN_MAX 100</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> LISTENQ 20</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> SERV_PORT 5000</span></span><br><span class="line"><span class="meta">#<span class="meta-keyword">define</span> INFTIM 1000</span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">void</span> <span class="title">setnonblocking</span><span class="params">(<span class="keyword">int</span> sock)</span></span>&#123;  </span><br><span class="line">    <span class="keyword">int</span> opts;  </span><br><span class="line">    opts=fcntl(sock,F_GETFL); </span><br><span class="line">    <span class="keyword">if</span>(opts&lt;<span class="number">0</span>)  &#123;    </span><br><span class="line">        perror(<span class="string">"fcntl(sock,GETFL)"</span>);   </span><br><span class="line">        <span class="built_in">exit</span>(<span class="number">1</span>);  </span><br><span class="line">    &#125; </span><br><span class="line">    opts = opts|O_NONBLOCK;  </span><br><span class="line">    <span class="keyword">if</span>(fcntl(sock,F_SETFL,opts)&lt;<span class="number">0</span>)  &#123; </span><br><span class="line">        perror(<span class="string">"fcntl(sock,SETFL,opts)"</span>);  </span><br><span class="line">        <span class="built_in">exit</span>(<span class="number">1</span>); </span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">(<span class="keyword">int</span> argc, <span class="keyword">char</span>* argv[])</span></span>&#123; </span><br><span class="line">    <span class="keyword">int</span> i, maxi, listenfd, connfd, sockfd,epfd,nfds, portnumber;  </span><br><span class="line">    <span class="keyword">ssize_t</span> n;  </span><br><span class="line">    <span class="keyword">char</span> <span class="built_in">line</span>[MAXLINE]; </span><br><span class="line">    <span class="keyword">socklen_t</span> clilen; </span><br><span class="line">    <span class="keyword">if</span> ( <span class="number">2</span> == argc ) &#123;   </span><br><span class="line">        <span class="keyword">if</span>( (portnumber = atoi(argv[<span class="number">1</span>])) &lt; <span class="number">0</span> ) &#123; </span><br><span class="line">            <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>,<span class="string">"Usage:%s portnumber/a/n"</span>,argv[<span class="number">0</span>]);   </span><br><span class="line">            <span class="keyword">return</span> <span class="number">1</span>;   </span><br><span class="line">        &#125; </span><br><span class="line">    &#125;  <span class="keyword">else</span>  &#123;  </span><br><span class="line">        <span class="built_in">fprintf</span>(<span class="built_in">stderr</span>,<span class="string">"Usage:%s portnumber/a/n"</span>,argv[<span class="number">0</span>]);  </span><br><span class="line">        <span class="keyword">return</span> <span class="number">1</span>; </span><br><span class="line">    &#125;  <span class="comment">//声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件 </span></span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">epoll_event</span> <span class="title">ev</span>,<span class="title">events</span>[20];</span>  <span class="comment">//生成用于处理accept的epoll专用的文件描述符 </span></span><br><span class="line">    epfd=epoll_create(<span class="number">256</span>); </span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">sockaddr_in</span> <span class="title">clientaddr</span>;</span>  </span><br><span class="line">    <span class="class"><span class="keyword">struct</span> <span class="title">sockaddr_in</span> <span class="title">serveraddr</span>;</span> </span><br><span class="line">    listenfd = socket(AF_INET, SOCK_STREAM, <span class="number">0</span>);  <span class="comment">//把socket设置为非阻塞方式 </span></span><br><span class="line">    <span class="comment">//setnonblocking(listenfd);  //设置与要处理的事件相关的文件描述符 </span></span><br><span class="line">    ev.data.fd=listenfd;  <span class="comment">//设置要处理的事件类型 </span></span><br><span class="line">    ev.events=EPOLLIN|EPOLLET; </span><br><span class="line">    <span class="comment">//ev.events=EPOLLIN;  //注册epoll事件 </span></span><br><span class="line">    epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&amp;ev); </span><br><span class="line">    bzero(&amp;serveraddr, <span class="keyword">sizeof</span>(serveraddr));</span><br><span class="line">    serveraddr.sin_family = AF_INET; </span><br><span class="line">    <span class="keyword">char</span> *local_addr=<span class="string">"127.0.0.1"</span>; </span><br><span class="line">    inet_aton(local_addr,&amp;(serveraddr.sin_addr));</span><br><span class="line">    <span class="comment">//htons(portnumber); </span></span><br><span class="line">    serveraddr.sin_port=htons(portnumber); </span><br><span class="line">    bind(listenfd,(sockaddr *)&amp;serveraddr, <span class="keyword">sizeof</span>(serveraddr));  </span><br><span class="line">    <span class="built_in">listen</span>(listenfd, LISTENQ);  </span><br><span class="line">    maxi = <span class="number">0</span>; </span><br><span class="line">    <span class="keyword">for</span> ( ; ; ) &#123;    <span class="comment">//等待epoll事件的发生   </span></span><br><span class="line">        nfds=epoll_wait(epfd,events,<span class="number">20</span>,<span class="number">500</span>);    <span class="comment">//处理所发生的所有事件  </span></span><br><span class="line">        <span class="keyword">for</span>(i=<span class="number">0</span>;i&lt;nfds;++i)   </span><br><span class="line">        &#123; </span><br><span class="line">            <span class="keyword">if</span>(events[i].data.fd==listenfd)<span class="comment">//如果新监测到一个SOCKET用户连接到了绑定的SOCKET端口，建立新的连接。  </span></span><br><span class="line">            &#123;       </span><br><span class="line">                connfd = accept(listenfd,(sockaddr *)&amp;clientaddr, &amp;clilen);     </span><br><span class="line">                <span class="keyword">if</span>(connfd&lt;<span class="number">0</span>)&#123;        </span><br><span class="line">                    perror(<span class="string">"connfd&lt;0"</span>);     </span><br><span class="line">                    <span class="built_in">exit</span>(<span class="number">1</span>);       </span><br><span class="line">                &#125;       </span><br><span class="line">                <span class="comment">//setnonblocking(connfd);    </span></span><br><span class="line">                <span class="keyword">char</span> *str = inet_ntoa(clientaddr.sin_addr);  </span><br><span class="line">                <span class="built_in">cout</span> &lt;&lt; <span class="string">"accapt a connection from "</span> &lt;&lt; str &lt;&lt; <span class="built_in">endl</span>;        <span class="comment">//设置用于读操作的文件描述符</span></span><br><span class="line">                ev.data.fd=connfd;        <span class="comment">//设置用于注测的读操作事件        </span></span><br><span class="line">                ev.events=EPOLLIN|EPOLLET;       </span><br><span class="line">                <span class="comment">//ev.events=EPOLLIN;       //注册ev    </span></span><br><span class="line">                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,&amp;ev);   </span><br><span class="line">            &#125;     </span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span>(events[i].events&amp;EPOLLIN)<span class="comment">//如果是已经连接的用户，并且收到数据，那么进行读入。 </span></span><br><span class="line">            &#123;       </span><br><span class="line">                <span class="built_in">cout</span> &lt;&lt; <span class="string">"EPOLLIN"</span> &lt;&lt; <span class="built_in">endl</span>;  </span><br><span class="line">                <span class="keyword">if</span> ( (sockfd = events[i].data.fd) &lt; <span class="number">0</span>)     </span><br><span class="line">                    <span class="keyword">continue</span>;       </span><br><span class="line">                <span class="keyword">if</span> ( (n = <span class="built_in">read</span>(sockfd, <span class="built_in">line</span>, MAXLINE)) &lt; <span class="number">0</span>) &#123;      </span><br><span class="line">                    <span class="keyword">if</span> (errno == ECONNRESET) &#123; </span><br><span class="line">                        <span class="built_in">close</span>(sockfd);         </span><br><span class="line">                        events[i].data.fd = <span class="number">-1</span>;      </span><br><span class="line">                    &#125; <span class="keyword">else</span>        </span><br><span class="line">                        <span class="built_in">std</span>::<span class="built_in">cout</span>&lt;&lt;<span class="string">"readline error"</span>&lt;&lt;<span class="built_in">std</span>::<span class="built_in">endl</span>;    </span><br><span class="line">                &#125; <span class="keyword">else</span> <span class="keyword">if</span> (n == <span class="number">0</span>) &#123;  </span><br><span class="line">                    <span class="built_in">close</span>(sockfd);      </span><br><span class="line">                    events[i].data.fd = <span class="number">-1</span>;    </span><br><span class="line">                &#125;    </span><br><span class="line">                line[n] = '/0';    </span><br><span class="line">                <span class="built_in">cout</span> &lt;&lt; <span class="string">"read "</span> &lt;&lt; <span class="built_in">line</span> &lt;&lt; <span class="built_in">endl</span>;        <span class="comment">//设置用于写操作的文件描述符</span></span><br><span class="line">                ev.data.fd=sockfd;        <span class="comment">//设置用于注测的写操作事件     </span></span><br><span class="line">                ev.events=EPOLLOUT|EPOLLET;        <span class="comment">//修改sockfd上要处理的事件为EPOLLOUT </span></span><br><span class="line">                <span class="comment">//epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&amp;ev);   </span></span><br><span class="line">            &#125;    </span><br><span class="line">            <span class="keyword">else</span> <span class="keyword">if</span>(events[i].events&amp;EPOLLOUT) <span class="comment">// 如果有数据发送  </span></span><br><span class="line">            &#123;        </span><br><span class="line">                 sockfd = events[i].data.fd;   </span><br><span class="line">                 <span class="built_in">write</span>(sockfd, <span class="built_in">line</span>, n);        <span class="comment">//设置用于读操作的文件描述符       </span></span><br><span class="line">                 ev.data.fd=sockfd;        <span class="comment">//设置用于注测的读操作事件        </span></span><br><span class="line">                 ev.events=EPOLLIN|EPOLLET;        <span class="comment">//修改sockfd上要处理的事件为EPOLIN        </span></span><br><span class="line">                 epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&amp;ev);      </span><br><span class="line">            &#125;   </span><br><span class="line">        &#125; </span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>


<p>客户端直接连接到这个服务器就好了。</p>
<p>原文：<a href="https://blog.csdn.net/ljx0305/article/details/4065058" target="_blank" rel="noopener">epoll使用详解（精髓）</a></p>

      
    </div>
    <footer class="article-footer">
      <a data-url="http://yoursite.com/epoll/" data-id="ckpb8zvm3004adsvla74yarlq" class="article-share-link">Share</a>
      
      
  <ul class="article-tag-list" itemprop="keywords"><li class="article-tag-list-item"><a class="article-tag-list-link" href="/tags/linux/" rel="tag">linux</a></li></ul>

    </footer>
  </div>
  
</article>


  


  <nav id="page-nav">
    
    <a class="extend prev" rel="prev" href="/page/3/">&amp;laquo; 上一页</a><a class="page-number" href="/">1</a><a class="page-number" href="/page/2/">2</a><a class="page-number" href="/page/3/">3</a><span class="page-number current">4</span><a class="page-number" href="/page/5/">5</a><a class="page-number" href="/page/6/">6</a><span class="space">&hellip;</span><a class="page-number" href="/page/13/">13</a><a class="extend next" rel="next" href="/page/5/">下一页 &amp;raquo;</a>
  </nav>

</section>
        
          <aside id="sidebar">
  
    

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">标签</h3>
    <div class="widget">
      <ul class="tag-list" itemprop="keywords"><li class="tag-list-item"><a class="tag-list-link" href="/tags/android/" rel="tag">android</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/data-structure/" rel="tag">data structure</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/docker/" rel="tag">docker</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/git/" rel="tag">git</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/go/" rel="tag">go</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/hexo/" rel="tag">hexo</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/java/" rel="tag">java</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/javascript/" rel="tag">javascript</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/json/" rel="tag">json</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/linux/" rel="tag">linux</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/maven/" rel="tag">maven</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mybatis/" rel="tag">mybatis</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/mysql/" rel="tag">mysql</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/network/" rel="tag">network</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/nginx/" rel="tag">nginx</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/nodejs/" rel="tag">nodejs</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/searching/" rel="tag">searching</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/sorting/" rel="tag">sorting</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/sublime-text/" rel="tag">sublime text</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/termux/" rel="tag">termux</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/theia/" rel="tag">theia</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/typora/" rel="tag">typora</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/vala/" rel="tag">vala</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/vim/" rel="tag">vim</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/vue/" rel="tag">vue</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/zig/" rel="tag">zig</a></li><li class="tag-list-item"><a class="tag-list-link" href="/tags/zookeeper/" rel="tag">zookeeper</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">标签云</h3>
    <div class="widget tagcloud">
      <a href="/tags/android/" style="font-size: 10px;">android</a> <a href="/tags/data-structure/" style="font-size: 10px;">data structure</a> <a href="/tags/docker/" style="font-size: 10px;">docker</a> <a href="/tags/git/" style="font-size: 15px;">git</a> <a href="/tags/go/" style="font-size: 10px;">go</a> <a href="/tags/hexo/" style="font-size: 10px;">hexo</a> <a href="/tags/java/" style="font-size: 18.33px;">java</a> <a href="/tags/javascript/" style="font-size: 11.67px;">javascript</a> <a href="/tags/json/" style="font-size: 10px;">json</a> <a href="/tags/linux/" style="font-size: 20px;">linux</a> <a href="/tags/maven/" style="font-size: 10px;">maven</a> <a href="/tags/mybatis/" style="font-size: 10px;">mybatis</a> <a href="/tags/mysql/" style="font-size: 11.67px;">mysql</a> <a href="/tags/network/" style="font-size: 11.67px;">network</a> <a href="/tags/nginx/" style="font-size: 10px;">nginx</a> <a href="/tags/nodejs/" style="font-size: 13.33px;">nodejs</a> <a href="/tags/searching/" style="font-size: 10px;">searching</a> <a href="/tags/sorting/" style="font-size: 16.67px;">sorting</a> <a href="/tags/sublime-text/" style="font-size: 10px;">sublime text</a> <a href="/tags/termux/" style="font-size: 10px;">termux</a> <a href="/tags/theia/" style="font-size: 10px;">theia</a> <a href="/tags/typora/" style="font-size: 10px;">typora</a> <a href="/tags/vala/" style="font-size: 10px;">vala</a> <a href="/tags/vim/" style="font-size: 15px;">vim</a> <a href="/tags/vue/" style="font-size: 11.67px;">vue</a> <a href="/tags/zig/" style="font-size: 10px;">zig</a> <a href="/tags/zookeeper/" style="font-size: 10px;">zookeeper</a>
    </div>
  </div>

  
    
  <div class="widget-wrap">
    <h3 class="widget-title">归档</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/05/">五月 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/04/">四月 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/03/">三月 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2021/01/">一月 2021</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/11/">十一月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/10/">十月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/09/">九月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/08/">八月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/07/">七月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/06/">六月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/05/">五月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/03/">三月 2020</a></li><li class="archive-list-item"><a class="archive-list-link" href="/archives/2020/02/">二月 2020</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/java-hashmap/">java.util.HashMap</a>
          </li>
        
          <li>
            <a href="/jvm/">JVM</a>
          </li>
        
          <li>
            <a href="/java-locks/">Java锁</a>
          </li>
        
          <li>
            <a href="/java-references/">Java引用</a>
          </li>
        
          <li>
            <a href="/gitea/">Gitea</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2021 Alanisia<br>
      Powered by <a href="http://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>


  
<link rel="stylesheet" href="/fancybox/jquery.fancybox.css">

  
<script src="/fancybox/jquery.fancybox.pack.js"></script>




<script src="/js/script.js"></script>




  </div>
</body>
</html>